package com.carnation.class_loader;

/**
 * <p>
 * JVM的类加载机制：BootstrapClassLoader ---> ExtClassLoader ---> AppClassLoader ---> CustomClassLoader ---> ThreadContextClassLoader
 * </p>
 *
 * @author: Sunny
 * @date: 2021/1/29
 * @version: v1.0.0
 */
public class LoadingMechanism {

    public static void main(String[] args) {
        bootstrapLoader();
        extLoader();
        appLoader();
    }

    /**
     * BootstrapClassLoader启动类加载器：加载的类库位置是"C:\Program Files\Java\jdk1.8.0_151\jre\lib".
     * 1：c++编写，已嵌入到了JVM内核当中。
     * 2：如何通过Java的类加载器获取到，ExtClassLoader的getParent()获取到的是null（在类加载器部分：null就是指BootstrapClassLoader）。
     * <p>
     * 1：BootstrapClassLoader加载的类库
     * System.getProperty("sun.boot.class.path”)
     * 结果：
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\sunrsasign.jar;
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;
     * C:\Program Files\Java\jdk1.8.0_151\jre\classes
     */
    private static void bootstrapLoader() {
        System.out.println(System.getProperty("sun.boot.class.path"));
    }

    /**
     * 扩展类加载器：加载的类库位置是"C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext".
     * 1：java编写，位于sun.misc包下，该包在你导入源代码的时候是没有的，需要重新去下，该包是openjdk的包，不公开源代码。
     * <p>
     * 1：ExtClassLoader加载的类库
     * System.getProperty("java.ext.dirs")
     * 结果：
     * C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext;
     * C:\Windows\Sun\Java\lib\ext
     */
    private static void extLoader() {
        System.out.println(System.getProperty("java.ext.dirs"));
    }

    /**
     * 应用程序类加载器：加载classpath下的class.
     * 1：java编写，位于sun.misc包下，该包是openjdk的包，不公开源代码
     * <p>
     * System.getProperty("java.class.path")的结果值就是AppClassLoader加载的类库。
     * 比较好的理解就是：idea上自己编写的普通类就是AppClassLoader加载的。
     */
    private static void appLoader() {
        System.out.println(System.getProperty("java.class.path"));
    }

    private static void threadLoader() {
        /**
         * 1：JVM会为每个线程设置默认TCCL为AppClassLoader
         * 子线程t线程会继承main的TCCL也为AppClassLoader
         */
        // main：sun.misc.Launcher$AppClassLoader@18b4aac2
        System.out.println(Thread.currentThread().getContextClassLoader());
        Thread t = new Thread(() -> System.out.println("xxx"));
        t.start();
        // t：sun.misc.Launcher$AppClassLoader@18b4aac2
        System.out.println(t.getContextClassLoader());

        /**
         * 2：主线程设置了TCCL为Test1
         * 子线程t1继承main的TCCL也为Test1（main和t的TCCL是一样的）
         */
        Thread.currentThread().setContextClassLoader(new Test1());
        // com.example.demo2.Test$Test1@79fc0f2f
        System.out.println(Thread.currentThread().getContextClassLoader());
        Thread t1 = new Thread(() -> System.out.println("xxx"));
        t1.start();
        // com.example.demo2.Test$Test1@79fc0f2f
        System.out.println(t1.getContextClassLoader());
    }

    /**
     * 自定义类加载器
     */
    public static class Test1 extends ClassLoader {
    }

}
